Skip to content

fix(nonce-reuse): verify recovered keys against pubkey and handle mixed s-normalization#18

Merged
oritwoen merged 1 commit into
mainfrom
fix/nonce-reuse-verify-and-negated-s
Mar 7, 2026
Merged

fix(nonce-reuse): verify recovered keys against pubkey and handle mixed s-normalization#18
oritwoen merged 1 commit into
mainfrom
fix/nonce-reuse-verify-and-negated-s

Conversation

@aeitwoen
Copy link
Copy Markdown
Collaborator

@aeitwoen aeitwoen commented Mar 6, 2026

Summary

  • When pubkey is available, verify recovered private key (d*G == pubkey) instead of returning unverified results
  • Try both s₂ polarities (original and negated) to handle signatures with mixed BIP62 low-s/high-s normalization
  • Without pubkey, behavior is unchanged (backward compatible)

Problem

The nonce-reuse attack previously returned the first mathematically valid private key without verifying it against the known public key. This caused two issues:

  1. No verification: A recovered key could be algebraically correct but wrong (e.g., if input data has errors)
  2. Mixed s-normalization: When one signature's s was BIP62-canonicalized (low-s) and the other wasn't, the standard formula k = (z₁-z₂)/(s₁-s₂) yields the wrong nonce, and recovery silently fails

Solution

When pubkey is present:

  • Compute d*G and compare against the provided pubkey (compressed and uncompressed)
  • Try both s₂ and -s₂, verifying each candidate — only return the key that matches
  • This follows the same pattern used by biased_nonce::verify_candidate and polynonce::verify_key

When pubkey is absent:

  • Original unverified formula, no behavior change

Tests

  • test_nonce_reuse_recovery_with_pubkey_verification — EC-consistent signatures with known d, verifies correct key recovery
  • test_nonce_reuse_recovery_negated_s_with_pubkey — Same setup but with s₂ negated, proves s-polarity handling works
  • All 73 existing tests pass, clippy clean

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants